import axios, {axiosConfig} from './Axios'
import Page from "@/models/core/Page";
import Pageable from "@/models/core/Pageable";
import Sort from "@/models/core/Sort";
import NamedString from "@/models/core/NamedString";
import {type ClassConstructor, plainToInstance} from "class-transformer";

export default class CrudApi<V, T, S> {
    public clazzV?: ClassConstructor<V>;
    public clazzT?: ClassConstructor<T>;

    protected readonly url: string;

    constructor(url: string) {
        this.url = url;
    }

    public search(search: S, pageable: Pageable, attrs?: any): Promise<Page<V>> {
        const config = axiosConfig<V>({}, search, pageable, attrs);
        return axios.get<Page<V>>(`${this.url}/search`, config)
            .then((data: Page<V>) => {
                const page = plainToInstance(Page<V>, data);
                page.content = plainToInstance(this.clazzV!, data.content);
                return page;
            });
    }

    public findAll(sort?: Sort): Promise<V[]> {
        return axios.get(`${this.url}/all`).then((data: V[]) => plainToInstance(this.clazzV!, data));
    }

    public findById(id: string | number): Promise<T> {
        return axios.get(`${this.url}/${id}`).then(data => plainToInstance(this.clazzT!, data));
    }

    public deleteById(id: string | number): Promise<void> {
        return axios.delete(`${this.url}/${id}`)
    }

    public deleteInBatch(ids: (string | number)[]): Promise<void> {
        const config = axiosConfig<void>({}, {
            id: ids
        })
        return axios.delete(`${this.url}/batch`, config)
    }

    public submit(data: T, row?: V): Promise<V> {
        return axios.put(this.url, data);
    }

    public dictAll(sort: Sort): Promise<NamedString[]> {
        const config = axiosConfig<NamedString>({}, sort);
        return axios.get(`${this.url}/dict`, config);
    }

    public sort(ids: string[] | number[], pageable: Pageable): Promise<void> {
        const config = axiosConfig<void>({}, {
            id: ids
        }, pageable);
        return axios.get(`${this.url}/sorting`, config);
    }

    public enable(id: string | number): Promise<void> {
        return axios.post(`${this.url}/${id}/enable`);
    }

    public disable(id: string | number): Promise<void> {
        return axios.post(`${this.url}/${id}/disable`);
    }

    public switch(id: string | number, dataIndex: string, value: boolean): Promise<void> {
        return axios.post(`${this.url}/${id}/${dataIndex}?${dataIndex}=${!value}`)
    }

    public enableInBatch(ids: (string | number)[]): Promise<void> {
        const config = axiosConfig<void>({}, {
            id: ids
        });
        return axios.get(`${this.url}/enable`, config);
    }

    public disableInBatch(ids: (string | number)[]): Promise<void> {
        const config = axiosConfig<void>({}, {
            id: ids
        });
        return axios.get(`${this.url}/disable`, config);
    }

}

/**
 * 本地操作的API，透传
 */
export class EmptyApi extends CrudApi<any, any, any> {
    constructor() {
        super("");
    }

    findById(id: string | number): Promise<any> {
        return Promise.resolve();
    }

    deleteById(id: string | number): Promise<void> {
        return Promise.resolve();
    }

    deleteInBatch(ids: (string | number)[]): Promise<void> {
        return Promise.resolve();
    }

    submit(data: any, row?: any): Promise<any> {
        return Promise.resolve(data);
    }
}
